/**
 *  Copyright (c) Filipe Manana <fdmanana@gmail.com>
 *  All rights reserved.
 * 
 *  This file is part of jsdet.
 *
 *  jsdet is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published
 *  by the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  jsdet is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with jsdet.  If not, see <http://www.gnu.org/licenses/>.
 *
 */


package jsdet.tests;


import jsdet.parsing.Parser;
import jsdet.parsing.ParsingStats;
import jsdet.parsing.enums.ClassMemberType;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import java.util.*;


/**
 * 
 * @author Filipe Manana
 *
 */
public class JavaScriptDetectionTest extends TestCase {

	public static Test suite() {
		TestSuite suite = new TestSuite();

		suite.addTest(new JavaScriptDetectionTest("testSimpleFunctionsDetection"));
		suite.addTest(new JavaScriptDetectionTest("testSimpleClasses_1_Detection"));
		suite.addTest(new JavaScriptDetectionTest("testSimpleClasses_2_Detection"));
		suite.addTest(new JavaScriptDetectionTest("testSimpleInheritance_1_Detection"));
		suite.addTest(new JavaScriptDetectionTest("testExtClasses_Detection"));
		suite.addTest(new JavaScriptDetectionTest("testClosureObjects_Detection"));

		return suite;
	}


	public JavaScriptDetectionTest(String testName) {
		super(testName);
	}


	@Override
	protected void setUp() throws Exception {
	}


	@Override
	protected void tearDown() throws Exception {
	}


	public void testSimpleFunctionsDetection() throws Exception {
		Parser parser = new Parser(TestsSettings.DETECTION_INPUT_FILES_DIR + "simple_functions.js");

		parser.doParsing();

		assertFalse(parser.hasErrors());

		ParsingStats stats = parser.getParsingStats();

		assertTrue(stats != null);

		Set<String> functions = stats.getFunctions();

		assertTrue(functions != null);
		assertTrue(functions.size() == 7);
		assertTrue(functions.contains("fun1"));
		assertTrue(functions.contains("fun2"));
		assertTrue(functions.contains("fun3"));
		assertTrue(functions.contains("fun4"));
		assertTrue(functions.contains("fun5"));
		assertTrue(functions.contains("fun6"));
		assertTrue(functions.contains("fun7"));
	}


	public void testSimpleClasses_1_Detection() throws Exception {
		Parser parser = new Parser(TestsSettings.DETECTION_INPUT_FILES_DIR + "simple_classes_1.js");

		parser.doParsing();

		assertFalse(parser.hasErrors());

		ParsingStats stats = parser.getParsingStats();

		assertTrue(stats != null);

		Set<String> functions = stats.getFunctions();

		assertTrue(functions != null);
		assertTrue(functions.size() == 2);
		assertTrue(functions.contains("normal_fun1"));
		assertTrue(functions.contains("normal_fun2"));

		Set<String> classes = stats.getClasses();

		assertTrue(classes != null);
		assertTrue(classes.size() == 2);
		assertTrue(classes.contains("Class_1"));
		assertTrue(classes.contains("Class_2"));

		Set<String> members = null;

		members = stats.getClassMembers("Class_1");

		assertTrue(members != null);
		assertTrue(members.size() == 3);
		assertTrue(stats.hasClassMember("Class_1", "number"));
		assertTrue(stats.hasClassMember("Class_1", "id"));
		assertTrue(stats.hasClassMember("Class_1", "name"));
		assertTrue(stats.isClassMemberOfType("Class_1", "number", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("Class_1", "id", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("Class_1", "name", ClassMemberType.NON_FUNCTION));

		members = stats.getClassMembers("Class_2");

		assertTrue(members != null);
		assertTrue(members.size() == 4);
		assertTrue(stats.hasClassMember("Class_2", "number"));
		assertTrue(stats.hasClassMember("Class_2", "config"));
		assertTrue(stats.hasClassMember("Class_2", "id"));
		assertTrue(stats.hasClassMember("Class_2", "getId"));
		assertTrue(stats.isClassMemberOfType("Class_2", "number", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("Class_2", "config", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("Class_2", "id", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("Class_2", "getId", ClassMemberType.FUNCTION));
	}


	public void testSimpleClasses_2_Detection() throws Exception {
		Parser parser = new Parser(TestsSettings.DETECTION_INPUT_FILES_DIR + "simple_classes_2.js");

		parser.doParsing();

		assertFalse(parser.hasErrors());

		ParsingStats stats = parser.getParsingStats();

		assertTrue(stats != null);

		Set<String> functions = stats.getFunctions();

		assertTrue(functions != null);
		assertTrue(functions.size() == 1);
		assertTrue(functions.contains("normal_fun1"));

		Set<String> classes = stats.getClasses();

		assertTrue(classes != null);
		assertTrue(classes.size() == 3);
		assertTrue(classes.contains("Class_1"));
		assertTrue(classes.contains("app.widget.Class_2"));
		assertTrue(classes.contains("app.widget.Panel"));

		Set<String> members = null;

		members = stats.getClassMembers("Class_1");

		assertTrue(members != null);
		assertTrue(members.size() == 2);
		assertTrue(stats.hasClassMember("Class_1", "id"));
		assertTrue(stats.hasClassMember("Class_1", "sayHello"));
		assertTrue(stats.isClassMemberOfType("Class_1", "id", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("Class_1", "sayHello", ClassMemberType.FUNCTION));
		assertTrue(stats.getClassInheritedMembers("Class_1").isEmpty());
		assertTrue(stats.getClassBaseHierarchy("Class_1").isEmpty());

		members = stats.getClassMembers("app.widget.Class_2");

		assertTrue(members != null);
		assertTrue(members.size() == 10);

		assertTrue(stats.hasClassMember("app.widget.Class_2", "id"));
		assertTrue(stats.hasClassMember("app.widget.Class_2", "name"));
		assertTrue(stats.hasClassMember("app.widget.Class_2", "me"));
		assertTrue(stats.hasClassMember("app.widget.Class_2", "method1"));
		assertTrue(stats.hasClassMember("app.widget.Class_2", "refresh"));
		assertTrue(stats.hasClassMember("app.widget.Class_2", "method2"));
		assertTrue(stats.hasClassMember("app.widget.Class_2", "method2_closure"));
		assertTrue(stats.hasClassMember("app.widget.Class_2", "sayHi"));
		assertTrue(stats.hasClassMember("app.widget.Class_2", "getId"));
		assertTrue(stats.hasClassMember("app.widget.Class_2", "toString"));
		assertTrue(stats.isClassMemberOfType("app.widget.Class_2", "id", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("app.widget.Class_2", "name", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("app.widget.Class_2", "me", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("app.widget.Class_2", "method1", ClassMemberType.FUNCTION));
		assertTrue(stats.isClassMemberOfType("app.widget.Class_2", "refresh", ClassMemberType.FUNCTION));
		assertTrue(stats.isClassMemberOfType("app.widget.Class_2", "method2", ClassMemberType.FUNCTION));
		assertTrue(stats.isClassMemberOfType("app.widget.Class_2", "method2_closure", ClassMemberType.FUNCTION));
		assertTrue(stats.isClassMemberOfType("app.widget.Class_2", "sayHi", ClassMemberType.FUNCTION));
		assertTrue(stats.isClassMemberOfType("app.widget.Class_2", "getId", ClassMemberType.FUNCTION));
		assertTrue(stats.isClassMemberOfType("app.widget.Class_2", "toString", ClassMemberType.FUNCTION));
		assertTrue(stats.getClassInheritedMembers("app.widget.Class_2").isEmpty());
		assertTrue(stats.getClassBaseHierarchy("app.widget.Class_2").isEmpty());

		members = stats.getClassMembers("app.widget.Panel");

		assertTrue(members != null);
		assertTrue(members.size() == 1);
		assertTrue(stats.hasClassMember("app.widget.Panel", "refresh"));
		assertTrue(stats.isClassMemberOfType("app.widget.Panel", "refresh", ClassMemberType.FUNCTION));
		assertTrue(stats.getClassInheritedMembers("app.widget.Panel").isEmpty());
		assertTrue(stats.getClassBaseHierarchy("app.widget.Panel").isEmpty());
	}


	public void testSimpleInheritance_1_Detection() throws Exception {
		Parser parser = new Parser(TestsSettings.DETECTION_INPUT_FILES_DIR + "simple_inheritance_1.js");

		parser.doParsing();

		assertFalse(parser.hasErrors());

		ParsingStats stats = parser.getParsingStats();

		assertTrue(stats != null);
		assertTrue(stats.getFunctions() != null);
		assertTrue(stats.getFunctions().isEmpty());

		Set<String> classes = stats.getClasses();

		assertTrue(classes != null);
		assertTrue(classes.size() == 4);
		assertTrue(classes.contains("MyBaseClass_1"));
		assertTrue(classes.contains("MySubclass_1"));
		assertTrue(classes.contains("myapp.MyBaseClass_2"));
		assertTrue(classes.contains("myapp.MySubclass_2"));
		assertTrue(stats.getClassBase("MyBaseClass_1") == null);
		assertTrue(stats.getClassBase("MySubclass_1") != null);
		assertTrue(stats.getClassBase("MySubclass_1").equals("MyBaseClass_1"));
		assertTrue(stats.getClassBase("myapp.MyBaseClass_2") == null);
		assertTrue(stats.getClassBase("myapp.MySubclass_2") != null);
		assertTrue(stats.getClassBase("myapp.MySubclass_2").equals("myapp.MyBaseClass_2"));

		Set<String> members = stats.getClassMembers("MyBaseClass_1");

		assertTrue(members != null);
		assertTrue(members.size() == 6);
		assertTrue(stats.hasClassMember("MyBaseClass_1", "id"));
		assertTrue(stats.hasClassMember("MyBaseClass_1", "config"));
		assertTrue(stats.hasClassMember("MyBaseClass_1", "panel"));
		assertTrue(stats.hasClassMember("MyBaseClass_1", "getId"));
		assertTrue(stats.hasClassMember("MyBaseClass_1", "refresh"));
		assertTrue(stats.hasClassMember("MyBaseClass_1", "init"));
		assertTrue(stats.isClassMemberOfType("MyBaseClass_1", "id", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("MyBaseClass_1", "config", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("MyBaseClass_1", "panel", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("MyBaseClass_1", "getId", ClassMemberType.FUNCTION));
		assertTrue(stats.isClassMemberOfType("MyBaseClass_1", "refresh", ClassMemberType.FUNCTION));
		assertTrue(stats.isClassMemberOfType("MyBaseClass_1", "init", ClassMemberType.FUNCTION));
		assertTrue(stats.getClassInheritedMembers("MyBaseClass_1").isEmpty());
		assertTrue(stats.getClassBaseHierarchy("MyBaseClass_1").isEmpty());

		members = stats.getClassMembers("MySubclass_1");

		assertTrue(members != null);
		assertTrue(members.size() == 3);
		assertTrue(stats.hasClassMember("MySubclass_1", "id"));
		assertTrue(stats.hasClassMember("MySubclass_1", "config"));
		assertTrue(stats.hasClassMember("MySubclass_1", "newMethod"));
		assertTrue(stats.isClassMemberOfType("MySubclass_1", "id", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("MySubclass_1", "config", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("MySubclass_1", "newMethod", ClassMemberType.FUNCTION));
		assertTrue(stats.getClassBaseHierarchy("MySubclass_1").size() == 1);
		assertTrue(stats.getClassBaseHierarchy("MySubclass_1").get(0).equals("MyBaseClass_1"));

		members = stats.getClassInheritedMembers("MySubclass_1");

		assertTrue(members.size() == 4);
		assertTrue(members.contains("panel"));
		assertTrue(members.contains("getId"));
		assertTrue(members.contains("refresh"));
		assertTrue(members.contains("init"));

		members = stats.getClassInheritedMembers("MySubclass_1", ClassMemberType.NON_FUNCTION);

		assertTrue(members.size() == 1);
		assertTrue(members.contains("panel"));

		members = stats.getClassInheritedMembers("MySubclass_1", ClassMemberType.FUNCTION);

		assertTrue(members.size() == 3);
		assertTrue(members.contains("getId"));
		assertTrue(members.contains("refresh"));
		assertTrue(members.contains("init"));

		assertTrue(stats.findFirstUpperClassWithMember("MySubclass_1", "doesntExist")== null);
		assertTrue(stats.findFirstUpperClassWithMember("MySubclass_1", "getId")!= null);
		assertTrue(stats.findFirstUpperClassWithMember("MySubclass_1", "getId").equals("MyBaseClass_1"));

		members = stats.getClassOverridingMembers("MySubclass_1");

		assertTrue(members.size() == 2);
		assertTrue(members.contains("id"));
		assertTrue(members.contains("config"));

		members = stats.getClassOverridingMembers("MySubclass_1", ClassMemberType.NON_FUNCTION);

		assertTrue(members.size() == 2);
		assertTrue(members.contains("id"));
		assertTrue(members.contains("config"));

		members = stats.getClassOverridingMembers("MySubclass_1", ClassMemberType.FUNCTION);

		assertTrue(members.isEmpty());

		members = stats.getClassMembers("myapp.MyBaseClass_2");

		assertTrue(members != null);
		assertTrue(members.size() == 3);
		assertTrue(stats.hasClassMember("myapp.MyBaseClass_2", "id"));
		assertTrue(stats.hasClassMember("myapp.MyBaseClass_2", "config"));
		assertTrue(stats.hasClassMember("myapp.MyBaseClass_2", "getId"));
		assertTrue(stats.isClassMemberOfType("myapp.MyBaseClass_2", "id", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("myapp.MyBaseClass_2", "config", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("myapp.MyBaseClass_2", "getId", ClassMemberType.FUNCTION));
		assertTrue(stats.getClassInheritedMembers("myapp.MyBaseClass_2").isEmpty());
		assertTrue(stats.getClassBaseHierarchy("myapp.MyBaseClass_2").isEmpty());

		members = stats.getClassMembers("myapp.MySubclass_2");

		assertTrue(members != null);
		assertTrue(members.size() == 3);
		assertTrue(stats.hasClassMember("myapp.MySubclass_2", "id"));
		assertTrue(stats.hasClassMember("myapp.MySubclass_2", "config"));
		assertTrue(stats.hasClassMember("myapp.MySubclass_2", "refresh"));
		assertTrue(stats.isClassMemberOfType("myapp.MySubclass_2", "id", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("myapp.MySubclass_2", "config", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("myapp.MySubclass_2", "refresh", ClassMemberType.FUNCTION));
		assertTrue(stats.getClassBaseHierarchy("myapp.MySubclass_2").size() == 1);
		assertTrue(stats.getClassBaseHierarchy("myapp.MySubclass_2").get(0).equals("myapp.MyBaseClass_2"));

		members = stats.getClassInheritedMembers("myapp.MySubclass_2");

		assertTrue(members.size() == 1);
		assertTrue(members.contains("getId"));

		members = stats.getClassInheritedMembers("myapp.MySubclass_2", ClassMemberType.NON_FUNCTION);

		assertTrue(members.isEmpty());

		members = stats.getClassInheritedMembers("myapp.MySubclass_2", ClassMemberType.FUNCTION);

		assertTrue(members.size() == 1);
		assertTrue(members.contains("getId"));

		assertTrue(stats.findFirstUpperClassWithMember("myapp.MySubclass_2", "doesntExist")== null);
		assertTrue(stats.findFirstUpperClassWithMember("myapp.MySubclass_2", "getId")!= null);
		assertTrue(stats.findFirstUpperClassWithMember("myapp.MySubclass_2", "getId").equals("myapp.MyBaseClass_2"));
		assertTrue(stats.findFirstUpperClassWithMember("myapp.MySubclass_2", "id")!= null);
		assertTrue(stats.findFirstUpperClassWithMember("myapp.MySubclass_2", "id").equals("myapp.MyBaseClass_2"));

		members = stats.getClassOverridingMembers("myapp.MySubclass_2");

		assertTrue(members.size() == 2);
		assertTrue(members.contains("id"));
		assertTrue(members.contains("config"));

		members = stats.getClassOverridingMembers("myapp.MySubclass_2", ClassMemberType.NON_FUNCTION);

		assertTrue(members.size() == 2);
		assertTrue(members.contains("id"));
		assertTrue(members.contains("config"));

		members = stats.getClassOverridingMembers("myapp.MySubclass_2", ClassMemberType.FUNCTION);

		assertTrue(members.isEmpty());
	}


	public void testExtClasses_Detection() throws Exception {
		Parser parser = new Parser(TestsSettings.DETECTION_INPUT_FILES_DIR + "ext_classes.js");

		parser.doParsing();

		assertFalse(parser.hasErrors());

		ParsingStats stats = parser.getParsingStats();

		assertTrue(stats != null);

		Set<String> functions = stats.getFunctions();

		assertTrue(functions != null);
		assertTrue(functions.size() == 0);

		Set<String> classes = stats.getClasses();

		assertTrue(classes != null);
		assertTrue(classes.size() == 8);
		assertTrue(classes.contains("BaseClass"));
		assertTrue(classes.contains("DerivedClass_1"));
		assertTrue(classes.contains("otherDerived"));
		assertTrue(classes.contains("Ext.Panel"));
		assertTrue(classes.contains("Ext.tree.Panel"));
		assertTrue(classes.contains("myapp.widget.Cart"));
		assertTrue(classes.contains("myapp.widget.FunCart"));
		assertTrue(classes.contains("myapp.widget.SimpleCart"));
		assertTrue(stats.getClassBase("BaseClass") == null);
		assertTrue(stats.getClassBase("DerivedClass_1") != null);
		assertTrue(stats.getClassBase("DerivedClass_1").equals("BaseClass"));
		assertTrue(stats.getClassBase("otherDerived") != null);
		assertTrue(stats.getClassBase("otherDerived").equals("Ext.tree.Panel"));
		assertTrue(stats.getClassBase("Ext.Panel") == null);
		assertTrue(stats.getClassBase("Ext.tree.Panel") == null);
		assertTrue(stats.getClassBase("myapp.widget.Cart") != null);
		assertTrue(stats.getClassBase("myapp.widget.Cart").equals("Ext.Panel"));
		assertTrue(stats.getClassBase("myapp.widget.FunCart") != null);
		assertTrue(stats.getClassBase("myapp.widget.FunCart").equals("myapp.widget.Cart"));
		assertTrue(stats.getClassBase("myapp.widget.SimpleCart") != null);
		assertTrue(stats.getClassBase("myapp.widget.SimpleCart").equals("myapp.widget.Cart"));

		assertTrue(stats.getClassMembers("Ext.Panel").isEmpty());
		assertTrue(stats.getClassMembers("Ext.tree.Panel").isEmpty());

		assertTrue(stats.getDerivedClasses("Ext.Panel").size() == 1);
		assertTrue(stats.getDerivedClasses("Ext.tree.Panel").size() == 1);

		assertTrue(stats.getDerivedClasses("Ext.Panel").contains("myapp.widget.Cart"));
		assertTrue(stats.getDerivedClasses("Ext.tree.Panel").contains("otherDerived"));

		Set<String> members = null;

		members = stats.getClassMembers("BaseClass");

		assertTrue(members != null);
		assertTrue(members.size() == 1);
		assertTrue(stats.hasClassMember("BaseClass", "id"));
		assertTrue(stats.isClassMemberOfType("BaseClass", "id", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.getClassBaseHierarchy("BaseClass").isEmpty());
		assertTrue(stats.getClassInheritedMembers("BaseClass").isEmpty());

		members = stats.getClassMembers("DerivedClass_1");

		assertTrue(members != null);
		assertTrue(members.size() == 2);
		assertTrue(stats.hasClassMember("DerivedClass_1", "id"));
		assertTrue(stats.hasClassMember("DerivedClass_1", "getId"));
		assertTrue(stats.isClassMemberOfType("DerivedClass_1", "id", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("DerivedClass_1", "getId", ClassMemberType.FUNCTION));
		assertTrue(stats.getClassBaseHierarchy("DerivedClass_1").size() == 1);
		assertTrue(stats.getClassBaseHierarchy("DerivedClass_1").get(0).equals("BaseClass"));
		assertTrue(stats.findFirstUpperClassWithMember("DerivedClass_1", "getId") == null);
		assertTrue(stats.findFirstUpperClassWithMember("DerivedClass_1", "id").equals("BaseClass"));

		members = stats.getClassInheritedMembers("DerivedClass_1");

		assertTrue(members.isEmpty());

		members = stats.getClassInheritedMembers("DerivedClass_1", ClassMemberType.NON_FUNCTION);

		assertTrue(members.isEmpty());

		members = stats.getClassInheritedMembers("DerivedClass_1", ClassMemberType.FUNCTION);

		assertTrue(members.isEmpty());

		members = stats.getClassOverridingMembers("DerivedClass_1");

		assertTrue(members.size() == 1);
		assertTrue(members.contains("id"));

		members = stats.getClassOverridingMembers("DerivedClass_1", ClassMemberType.NON_FUNCTION);

		assertTrue(members.size() == 1);
		assertTrue(members.contains("id"));

		members = stats.getClassOverridingMembers("DerivedClass_1", ClassMemberType.FUNCTION);

		assertTrue(members.isEmpty());

		members = stats.getClassMembers("otherDerived");

		assertTrue(members != null);
		assertTrue(members.size() == 7);
		assertTrue(stats.hasClassMember("otherDerived", "id"));
		assertTrue(stats.hasClassMember("otherDerived", "name"));
		assertTrue(stats.hasClassMember("otherDerived", "getId"));
		assertTrue(stats.hasClassMember("otherDerived", "getName"));
		assertTrue(stats.hasClassMember("otherDerived", "otherMethod"));
		assertTrue(stats.hasClassMember("otherDerived", "closure"));
		assertTrue(stats.hasClassMember("otherDerived", "refresh"));
		assertTrue(stats.isClassMemberOfType("otherDerived", "id", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("otherDerived", "name", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("otherDerived", "getId", ClassMemberType.FUNCTION));
		assertTrue(stats.isClassMemberOfType("otherDerived", "getName", ClassMemberType.FUNCTION));
		assertTrue(stats.isClassMemberOfType("otherDerived", "otherMethod", ClassMemberType.FUNCTION));
		assertTrue(stats.isClassMemberOfType("otherDerived", "closure", ClassMemberType.FUNCTION));
		assertTrue(stats.isClassMemberOfType("otherDerived", "refresh", ClassMemberType.FUNCTION));
		assertTrue(stats.getClassBaseHierarchy("otherDerived").size() == 1);
		assertTrue(stats.getClassBaseHierarchy("otherDerived").get(0).equals("Ext.tree.Panel"));
		assertTrue(stats.getClassInheritedMembers("otherDerived").isEmpty());

		members = stats.getClassMembers("myapp.widget.Cart");

		assertTrue(members != null);
		assertTrue(members.size() == 5);
		assertTrue(stats.hasClassMember("myapp.widget.Cart", "config"));
		assertTrue(stats.hasClassMember("myapp.widget.Cart", "fieldWidth"));
		assertTrue(stats.hasClassMember("myapp.widget.Cart", "init"));
		assertTrue(stats.hasClassMember("myapp.widget.Cart", "getConfig"));
		assertTrue(stats.hasClassMember("myapp.widget.Cart", "refresh"));
		assertTrue(stats.isClassMemberOfType("myapp.widget.Cart", "config", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("myapp.widget.Cart", "fieldWidth", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("myapp.widget.Cart", "init", ClassMemberType.FUNCTION));
		assertTrue(stats.isClassMemberOfType("myapp.widget.Cart", "getConfig", ClassMemberType.FUNCTION));
		assertTrue(stats.isClassMemberOfType("myapp.widget.Cart", "refresh", ClassMemberType.FUNCTION));
		assertTrue(stats.getClassBaseHierarchy("myapp.widget.Cart").size() == 1);
		assertTrue(stats.getClassBaseHierarchy("myapp.widget.Cart").get(0).equals("Ext.Panel"));
		assertTrue(stats.getClassInheritedMembers("myapp.widget.Cart").isEmpty());

		members = stats.getClassMembers("myapp.widget.FunCart");

		assertTrue(members != null);
		assertTrue(members.size() == 1);
		assertTrue(stats.hasClassMember("myapp.widget.FunCart", "refresh"));
		assertTrue(stats.isClassMemberOfType("myapp.widget.FunCart", "refresh", ClassMemberType.FUNCTION));
		assertTrue(stats.getClassBaseHierarchy("myapp.widget.FunCart").size() == 2);
		assertTrue(stats.getClassBaseHierarchy("myapp.widget.FunCart").get(0).equals("myapp.widget.Cart"));
		assertTrue(stats.getClassBaseHierarchy("myapp.widget.FunCart").get(1).equals("Ext.Panel"));

		members = stats.getClassInheritedMembers("myapp.widget.FunCart");

		assertTrue(members.size() == 4);
		assertTrue(members.contains("config"));
		assertTrue(members.contains("fieldWidth"));
		assertTrue(members.contains("init"));
		assertTrue(members.contains("getConfig"));

		members = stats.getClassInheritedMembers("myapp.widget.FunCart", ClassMemberType.NON_FUNCTION);

		assertTrue(members.size() == 2);
		assertTrue(members.contains("config"));
		assertTrue(members.contains("fieldWidth"));

		members = stats.getClassInheritedMembers("myapp.widget.FunCart", ClassMemberType.FUNCTION);

		assertTrue(members.size() == 2);
		assertTrue(members.contains("init"));
		assertTrue(members.contains("getConfig"));

		assertTrue(stats.findFirstUpperClassWithMember("myapp.widget.FunCart", "config").equals("myapp.widget.Cart"));
		assertTrue(stats.findFirstUpperClassWithMember("myapp.widget.FunCart", "fieldWidth").equals("myapp.widget.Cart"));
		assertTrue(stats.findFirstUpperClassWithMember("myapp.widget.FunCart", "init").equals("myapp.widget.Cart"));
		assertTrue(stats.findFirstUpperClassWithMember("myapp.widget.FunCart", "getConfig").equals("myapp.widget.Cart"));

		members = stats.getClassOverridingMembers("myapp.widget.FunCart");

		assertTrue(members.size() == 1);
		assertTrue(members.contains("refresh"));

		members = stats.getClassOverridingMembers("myapp.widget.FunCart", ClassMemberType.NON_FUNCTION);

		assertTrue(members.isEmpty());

		members = stats.getClassOverridingMembers("myapp.widget.FunCart", ClassMemberType.FUNCTION);

		assertTrue(members.size() == 1);
		assertTrue(members.contains("refresh"));

		members = stats.getClassMembers("myapp.widget.SimpleCart");

		assertTrue(members != null);
		assertTrue(members.size() == 2);
		assertTrue(stats.hasClassMember("myapp.widget.SimpleCart", "newField"));
		assertTrue(stats.hasClassMember("myapp.widget.SimpleCart", "init"));
		assertTrue(stats.isClassMemberOfType("myapp.widget.SimpleCart", "newField", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClassMemberOfType("myapp.widget.SimpleCart", "init", ClassMemberType.FUNCTION));
		assertTrue(stats.getClassBaseHierarchy("myapp.widget.SimpleCart").size() == 2);
		assertTrue(stats.getClassBaseHierarchy("myapp.widget.SimpleCart").get(0).equals("myapp.widget.Cart"));
		assertTrue(stats.getClassBaseHierarchy("myapp.widget.SimpleCart").get(1).equals("Ext.Panel"));

		members = stats.getClassInheritedMembers("myapp.widget.SimpleCart");

		assertTrue(members.size() == 4);
		assertTrue(members.contains("config"));
		assertTrue(members.contains("fieldWidth"));
		assertTrue(members.contains("refresh"));
		assertTrue(members.contains("getConfig"));

		members = stats.getClassInheritedMembers("myapp.widget.SimpleCart", ClassMemberType.NON_FUNCTION);

		assertTrue(members.size() == 2);
		assertTrue(members.contains("config"));
		assertTrue(members.contains("fieldWidth"));

		members = stats.getClassInheritedMembers("myapp.widget.SimpleCart", ClassMemberType.FUNCTION);

		assertTrue(members.size() == 2);
		assertTrue(members.contains("refresh"));
		assertTrue(members.contains("getConfig"));

		assertTrue(stats.findFirstUpperClassWithMember("myapp.widget.SimpleCart", "config").equals("myapp.widget.Cart"));
		assertTrue(stats.findFirstUpperClassWithMember("myapp.widget.SimpleCart", "fieldWidth").equals("myapp.widget.Cart"));
		assertTrue(stats.findFirstUpperClassWithMember("myapp.widget.SimpleCart", "refresh").equals("myapp.widget.Cart"));
		assertTrue(stats.findFirstUpperClassWithMember("myapp.widget.SimpleCart", "getConfig").equals("myapp.widget.Cart"));
		assertTrue(stats.findFirstUpperClassWithMember("myapp.widget.SimpleCart", "doesntExist") == null);

		members = stats.getClassOverridingMembers("myapp.widget.SimpleCart");

		assertTrue(members.size() == 1);
		assertTrue(members.contains("init"));

		members = stats.getClassOverridingMembers("myapp.widget.SimpleCart", ClassMemberType.NON_FUNCTION);

		assertTrue(members.isEmpty());

		members = stats.getClassOverridingMembers("myapp.widget.SimpleCart", ClassMemberType.FUNCTION);

		assertTrue(members.size() == 1);
		assertTrue(members.contains("init"));
	}


	public void testClosureObjects_Detection() throws Exception {
		Parser parser = new Parser(TestsSettings.DETECTION_INPUT_FILES_DIR + "closure_objects.js");

		parser.doParsing();

		assertFalse(parser.hasErrors());

		ParsingStats stats = parser.getParsingStats();

		assertTrue(stats != null);

		Set<String> functions = stats.getFunctions();

		assertTrue(functions != null);
		assertTrue(functions.isEmpty());

		Set<String> classes = stats.getClasses();

		assertTrue(classes != null);
		assertTrue(classes.isEmpty());

		Set<String> closureObjects = stats.getClosureObjects();

		assertTrue(closureObjects != null);
		assertTrue(closureObjects.size() == 2);
		assertTrue(stats.hasClosureObject("closureObj_1"));
		assertTrue(stats.hasClosureObject("closureObj_2"));

		assertTrue(stats.getClosureObjectMembers("closureObj_1").size() == 3);
		assertTrue(stats.hasClosureObjectMember("closureObj_1", "id"));
		assertTrue(stats.hasClosureObjectMember("closureObj_1", "method_1"));
		assertTrue(stats.hasClosureObjectMember("closureObj_1", "method_2"));
		assertTrue(stats.isClosureObjectMemberOfType("closureObj_1", "id", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClosureObjectMemberOfType("closureObj_1", "method_1", ClassMemberType.FUNCTION));
		assertTrue(stats.isClosureObjectMemberOfType("closureObj_1", "method_2", ClassMemberType.FUNCTION));

		assertTrue(stats.getClosureObjectMembers("closureObj_2").size() == 3);
		assertTrue(stats.hasClosureObjectMember("closureObj_2", "id"));
		assertTrue(stats.hasClosureObjectMember("closureObj_2", "init"));
		assertTrue(stats.hasClosureObjectMember("closureObj_2", "refresh"));
		assertTrue(stats.isClosureObjectMemberOfType("closureObj_2", "id", ClassMemberType.NON_FUNCTION));
		assertTrue(stats.isClosureObjectMemberOfType("closureObj_2", "init", ClassMemberType.FUNCTION));
		assertTrue(stats.isClosureObjectMemberOfType("closureObj_2", "refresh", ClassMemberType.FUNCTION));
	}
}
